package cc.md888.app.application.proxy.impl;

import cc.md888.app.application.proxy.ProxyInfoLookup;
import cc.md888.app.enums.ProxyProtocolEnum;
import cc.md888.app.exception.BizRuntimeException;
import cc.md888.app.infr.ip.IpInfoVO;
import cc.md888.app.infr.ip.convert.Ip123Convert;
import cc.md888.app.model.proxy.ProxyInfoCmd;
import cc.md888.result.ResultCode;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * 使用curl命令获取代理信息
 */
@Component
@Slf4j
public class CurlProxyInfoLookup implements ProxyInfoLookup {

    @Override
    public IpInfoVO lookup(ProxyInfoCmd cmd) {
        StringBuilder proxy = new StringBuilder();
        proxy.append(cmd.getProtocol().toLowerCase()).append("://");

        if (StringUtils.isNotEmpty(cmd.getUsername())) {
            proxy.append(cmd.getUsername()).append(":").append(cmd.getPassword())
                    .append("@");
        }

        proxy.append(cmd.getHost()).append(":").append(cmd.getPort());

        String target = "https://www.ip123.in/ip.json";

        String[] curl = new String[]{"curl", "-x",  proxy.toString() , target};
        log.info("lookup proxy curl : {}", String.join(" ", curl));
        try {
            Process process = new ProcessBuilder(curl)
                    .start();

            boolean success = process.waitFor(30, TimeUnit.SECONDS);
            if(!success) {
                throw BizRuntimeException.from(ResultCode.ERROR, "curl timeout");
            }

            int exitCode = process.exitValue();
            if(exitCode != 0) {
                String error = IOUtils.toString(process.getErrorStream(), StandardCharsets.UTF_8);
                log.error("fail to lookup proxy, exit code: {} , error: {}", exitCode, error);
                throw BizRuntimeException.from(ResultCode.ERROR, "fail to lookup proxy, exit code: " + exitCode);
            }

            String body = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8);
            log.info("lookup proxy body : {}", body);
            if(StringUtils.isEmpty(body)) {
                throw BizRuntimeException.from(ResultCode.ERROR, "fail to lookup proxy");
            }
            return new Ip123Convert().convert(body);
        } catch (Exception e) {
            log.error("lookup proxy error ", e);
            throw BizRuntimeException.from(ResultCode.ERROR, "获取代理信息失败，请稍后再试" );
        }
    }

    public static void main(String[] args) {
        ProxyInfoCmd cmd = new ProxyInfoCmd();
        cmd.setProtocol(ProxyProtocolEnum.Socks5.name());
        cmd.setHost("127.0.0.1");
        cmd.setPort(10808);
        cmd.setUsername("xx");
        cmd.setPassword("xx");
        IpInfoVO ipInfoVO = new CurlProxyInfoLookup().lookup(cmd);
        System.out.println(JSON.toJSONString(ipInfoVO));
    }

}
